﻿Imports ICSharpCode.SharpZipLib
Imports System.IO
Imports ICSharpCode.SharpZipLib.GZip
Imports ICSharpCode.SharpZipLib.Zip
Imports ICSharpCode.SharpZipLib.Tar
Imports ICSharpCode.SharpZipLib.Core
Imports System.Web.UI
'created by : sum 
'created date: 13/9/2011
'description: compress helper, easy me to do compress and extract:D
'information : http://wiki.sharpdevelop.net/SharpZipLib-Zip-Samples.ashx
Namespace helper
    Public NotInheritable Class CompressHelper

        ''' <summary>
        ''' Extract GZip
        ''' </summary>
        ''' <param name="gzipFileName">gzip file path</param>
        ''' <param name="targetDir">target directory</param>
        ''' <remarks></remarks>
        Public Shared Sub ExtractGZip(ByVal gzipFileName As String, ByVal targetDir As String)

            Dim dataBuffer As Byte() = New Byte(4095) {}

            Using fs As System.IO.Stream = New FileStream(gzipFileName, FileMode.Open, FileAccess.Read)
                Using gzipStream As New GZipInputStream(fs)

                    ' Change this to your needs
                    Dim fnOut As String = Path.Combine(targetDir, Path.GetFileNameWithoutExtension(gzipFileName))

                    Using fsOut As FileStream = File.Create(fnOut)
                        StreamUtils.Copy(gzipStream, fsOut, dataBuffer)
                    End Using
                End Using
            End Using
        End Sub

        ''' <summary>
        ''' Extract Zip
        ''' </summary>
        ''' <param name="zipFileName">zip file path</param>
        ''' <param name="targetDir">target directory</param>
        ''' <remarks></remarks>
        Public Shared Sub ExtractZip(ByVal zipFileName As String, ByVal targetDir As String)
            Dim dataBuffer As Byte() = New Byte(4095) {}

            Using fs As System.IO.Stream = New FileStream(zipFileName, FileMode.Open, FileAccess.Read)
                Using zipStream As New ZipInputStream(fs)

                    ' Change this to your needs
                    Dim fnOut As String = Path.Combine(targetDir, Path.GetFileNameWithoutExtension(zipFileName))

                    Using fsOut As FileStream = File.Create(fnOut)
                        StreamUtils.Copy(zipStream, fsOut, dataBuffer)
                    End Using
                End Using
            End Using
        End Sub


        ''' <summary>
        ''' Extract Tar
        ''' </summary>
        ''' <param name="tarFileName">Tar file path</param>
        ''' <param name="targetDir">target directory</param>
        ''' <remarks></remarks>
        Public Shared Sub ExtractTar(ByVal tarFileName As String, ByVal targetDir As String)
            Dim dataBuffer As Byte() = New Byte() {}

            Using fs As System.IO.Stream = New FileStream(tarFileName, FileMode.Open, FileAccess.Read)
                Using tarStream As New TarInputStream(fs)

                    ' Change this to your needs
                    Dim fnOut As String = Path.Combine(targetDir, Path.GetFileNameWithoutExtension(tarFileName))

                    Using fsOut As FileStream = File.Create(fnOut)
                        StreamUtils.Copy(tarStream, fsOut, dataBuffer)
                    End Using
                End Using
            End Using
        End Sub




        ''' <summary>
        ''' compress zip
        ''' </summary>
        ''' <param name="outPathname">out path name</param>
        ''' <param name="password">password</param>
        ''' <param name="folderName">target folder name</param>
        ''' <remarks></remarks>
        Public Sub compressZip(ByVal outPathname As String, ByVal password As String, ByVal folderName As String)

            Dim fsOut As FileStream = File.Create(outPathname)
            Dim zipStream As New ZipOutputStream(fsOut)

            zipStream.SetLevel(3)       '0-9, 9 being the highest level of compression
            zipStream.Password = password   ' optional. Null is the same as not setting.

            ' This setting will strip the leading part of the folder path in the entries, to
            ' make the entries relative to the starting folder.
            ' To include the full path for each entry up to the drive root, assign folderOffset = 0.
            Dim folderOffset As Integer = folderName.Length + (If(folderName.EndsWith("\"), 0, 1))

            CompressFolder(folderName, zipStream, folderOffset)

            zipStream.IsStreamOwner = True
            ' Makes the Close also Close the underlying stream
            zipStream.Close()
        End Sub

        ' Recurses down the folder structure  '
        Private Shared Sub CompressFolder(ByVal path As String, ByVal zipStream As ZipOutputStream, ByVal folderOffset As Integer)

            Dim files As String() = Directory.GetFiles(path)

            For Each filename As String In files

                Dim fi As New FileInfo(filename)

                Dim entryName As String = filename.Substring(folderOffset)  ' Makes the name in zip based on the folder
                entryName = ZipEntry.CleanName(entryName)       ' Removes drive from name and fixes slash direction
                Dim newEntry As New ZipEntry(entryName)
                newEntry.DateTime = fi.LastWriteTime            ' Note the zip format stores 2 second granularity

                ' Specifying the AESKeySize triggers AES encryption. Allowable values are 0 (off), 128 or 256.
                '   newEntry.AESKeySize = 256;

                ' To permit the zip to be unpacked by built-in extractor in WinXP and Server2003, WinZip 8, Java, and other older code,
                ' you need to do one of the following: Specify UseZip64.Off, or set the Size.
                ' If the file may be bigger than 4GB, or you do not need WinXP built-in compatibility, you do not need either,
                ' but the zip will be in Zip64 format which not all utilities can understand.
                '   zipStream.UseZip64 = UseZip64.Off;
                newEntry.Size = fi.Length

                zipStream.PutNextEntry(newEntry)

                ' Zip the file in buffered chunks
                ' the "using" will close the stream even if an exception occurs
                Dim buffer As Byte() = New Byte(4095) {}
                Using streamReader As FileStream = File.OpenRead(filename)
                    StreamUtils.Copy(streamReader, zipStream, buffer)
                End Using
                zipStream.CloseEntry()
            Next
            Dim folders As String() = Directory.GetDirectories(path)
            For Each folder As String In folders
                CompressFolder(folder, zipStream, folderOffset)
            Next
        End Sub



        ' This will accumulate each of the files named in the fileList into a zip file,
        ' and stream it to the browser.
        ' This approach writes directly to the Response OutputStream.
        ' The browser starts to receive data immediately which should avoid timeout problems.
        ' This also avoids an intermediate memorystream, saving memory on large files.
        ''' <summary>
        ''' This will accumulate each of the files named in the fileList into a zip file,and stream it to the browser.This approach writes directly to the Response OutputStream.The browser starts to receive data immediately which should avoid timeout problems.This also avoids an intermediate memorystream, saving memory on large files.
        ''' </summary>
        ''' <param name="page">page</param>
        ''' <param name="zipFileList">list of zile file name</param>
        ''' <remarks></remarks>
        Public Shared Sub ResponseZip(ByVal page As Page, ByVal zipFileList As List(Of String))
            page.Response.Clear()
            page.Response.ContentType = "application/zip"
            ' If the browser is receiving a mangled zipfile, IIS Compression may cause this problem. Some members have found that
            '    Response.ContentType = "application/octet-stream"     has solved this. May be specific to Internet Explorer.

            page.Response.AppendHeader("content-disposition", "attachment; filename=""Download.zip""")
            page.Response.CacheControl = "Private"
            page.Response.Cache.SetExpires(DateTime.Now.AddMinutes(3))
            ' or put a timestamp in the filename in the content-disposition
            Dim buffer As Byte() = New Byte(4095) {}

            Dim zipOutputStream As New ZipOutputStream(page.Response.OutputStream)
            zipOutputStream.SetLevel(3)     '0-9, 9 being the highest level of compression
            For Each fileName As String In zipFileList

                Dim fs As Stream = File.OpenRead(fileName)
                ' or any suitable inputstream
                Dim entry As New ZipEntry(ZipEntry.CleanName(fileName))
                entry.Size = fs.Length
                ' Setting the Size provides WinXP built-in extractor compatibility,
                '  but if not available, you can set zipOutputStream.UseZip64 = UseZip64.Off instead.

                zipOutputStream.PutNextEntry(entry)

                Dim count As Integer = fs.Read(buffer, 0, buffer.Length)
                While count > 0
                    zipOutputStream.Write(buffer, 0, count)
                    count = fs.Read(buffer, 0, buffer.Length)
                    If Not page.Response.IsClientConnected Then
                        Exit While
                    End If
                    page.Response.Flush()
                End While
                fs.Close()
            Next
            zipOutputStream.Close()

            page.Response.Flush()
            page.Response.End()
        End Sub
    End Class
End Namespace

